package com.sise.cn.task.service;

import com.sise.cn.task.enumerate.ServerResponseEnum;
import com.sise.cn.task.exception.TaskException;
import com.sise.cn.task.po.JobPO;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.TimeZone;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author 龚秀峰
 * @version 1.0
 * @date 2020/6/8 15:09
 */
@Slf4j
@Service
public class ScheduledTask {

    private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

    private static ThreadPoolExecutor executor;

    static {
//        startScheduleJobs();
//        try {
//            Properties properties = new Properties();
//            ClassPathResource resource = new ClassPathResource("version.properties");
//            properties.load(new InputStreamReader(resource.getInputStream()));
//            schedulerFactory = new StdSchedulerFactory(properties);
//        } catch (Exception e) {
//            log.error("", e);
//        }
    }

    @PostConstruct
    public static void init() {
        executor = new ThreadPoolExecutor(150, 150,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(), new CustomerThreadFactory());
    }

    /**
     * 防止构造
     */
    private ScheduledTask() {

    }

    public static void addScheduleJob(JobPO jobPojo, Class<? extends Job> jobClass) {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            // 任务名，任务组，任务执行类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobPojo.getName(), jobPojo.getJobGroup()).build();
            // 触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组
            triggerBuilder.withIdentity(jobPojo.getTriggerName(), jobPojo.getTriggerGroup())
                    .withPriority(Integer.parseInt(jobPojo.getPriority()))
                    .startNow()
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobPojo.getJobCorn())
                            .inTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))
                            .withMisfireHandlingInstructionFireAndProceed())
                    .build();
            // 触发器时间设定
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(jobPojo.getJobCorn()));
            // 创建Trigger对象
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();
            // 调度容器设置JobDetail和Trigger
            scheduler.scheduleJob(jobDetail, trigger);
            // 启动
//            if (!scheduler.isShutdown()) {
//                scheduler.start();
//            }
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    /**
     * 删除一个任务
     */
    public static void deleteScheduleJob(JobPO job) {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(job.getTriggerName(), job.getTriggerGroup());
            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(JobKey.jobKey(job.getName(), job.getJobGroup()));
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    public static void deleteScheduleJob(JobKey jobKey, TriggerKey triggerKey) {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(jobKey);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    /**
     * 暂停一个任务
     */
    public static void pauseScheduleJob(JobPO job) {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            scheduler.pauseJob(JobKey.jobKey(job.getName(), job.getJobGroup()));
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    /**
     * 恢复一个暂停任务
     */
    public static void resumeScheduleJob(JobPO job) {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            scheduler.resumeJob(JobKey.jobKey(job.getName(), job.getJobGroup()));
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    /**
     * 启动所有定时任务
     */
    public static void startScheduleJobs() {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            if (!scheduler.isShutdown()) {
                scheduler.start();
            }
        } catch (Exception e) {
            log.error("", e);
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    /**
     * 暂停所有任务
     */
    public static void pauseScheduleJobs() {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            scheduler.pauseAll();
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    /**
     * 恢复所有暂停任务
     */
    public static void resumeScheduleJobs() {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            scheduler.resumeAll();
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    /**
     * 关闭所有定时任务
     */
    public static void shutdownScheduleJobs() {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            if (!scheduler.isShutdown()) {
                scheduler.shutdown();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    /**
     * 关闭所有定时任务
     */
    public static void shutdownScheduleJobs(boolean waitForJobsToComplete) {
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            if (!scheduler.isShutdown()) {
                scheduler.shutdown(waitForJobsToComplete);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    public static void submitTask(Runnable runnable) {
        executor.execute(runnable);
    }

    public static void submitTask(Class<? extends AbstractTask> clazz) {
        try {
            Runnable run = clazz.getDeclaredConstructor().newInstance();
            executor.execute(run);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new TaskException(ServerResponseEnum.TASK_ERROR);
        }
    }

    private static class CustomerThreadFactory implements ThreadFactory {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("TaskThread:" + t.getName());
            t.setDaemon(true);
            return t;
        }
    }
}
